package com.summer.data.connection.session;

import com.summer.data.exception.BaseException;
import com.summer.data.connection.*;
import com.summer.data.exception.SqlException;
import com.summer.data.type.Callback;

import java.sql.Connection;
import java.sql.SQLException;

/**
 * 支持事务的 session
 * @author 345480567@qq.com
 */
public class TransactionSession extends NormalSession implements Transaction {

    TransactionDef txDef;

    Connection connection;

    private boolean oldAutoCommit = true;

    public TransactionSession(SessionFactory sessionFactory, TransactionDef txDef) {
        super(sessionFactory);
        this.txDef = txDef;
    }

    @Override
    public void commit() {
        try {
            connection.commit();
        } catch (SQLException e) {
            throw new BaseException(e);
        }
    }

    @Override
    public void rollback() {
        try {
            connection.rollback();
        } catch (SQLException e) {
            throw new BaseException(e);
        }
    }

    @Override
    public Connection getConnection() {
        super.getConnection();
        try {
            // 保存连接的原来 commit 状态
            oldAutoCommit = connection.getAutoCommit();

            connection.setAutoCommit(false);
            connection.setTransactionIsolation(txDef.isolation.getValue());
        } catch (SQLException e) {
            throw new SqlException(e);
        }
        return connection;
    }

    @Override
    public void close() {
        requests--;
        if (requests == 0) {
            if (connection != null) {
                try {
                    connection.close();
                } catch (SQLException e) {
                    throw new SqlException(e);
                }
            }
        }
    }

    // todo:
    public void begin(Callback callback) {
        try {
            getConnection();
            callback.apply();
            commit();
            connection.setAutoCommit(oldAutoCommit);
        } catch (SQLException e) {
            rollback();
        } finally {
            close();
        }
    }

}
